﻿using Infrastructure.Cache.CacheItemPolicyPackage;
using System;
using System.Runtime.Caching;

namespace Infrastructure.Cache
{
    /// <summary>
    /// 缓存池封装
    /// </summary>
    public class RuntimeCachePool
    {
        private readonly ObjectCache _cache = MemoryCache.Default;
        private ICacheItemPolicy _cacheItemPolicy;

        /// <summary>
        /// 缓存池
        /// 默认过期时间为当晚12点
        /// </summary>
        public RuntimeCachePool() => _cacheItemPolicy = new AbsoluteCacheItemPolicy(DateTimeOffset.Now.Date.AddDays(1));

        /// <summary>
        /// 将传入值作为过期时间
        /// </summary>
        /// <param name="expireTime">过期时间</param>
        public void ChangeAbsoluteExpiration(DateTimeOffset expireTime)
        {
            _cacheItemPolicy = new AbsoluteCacheItemPolicy(expireTime);
        }

        /// <summary>
        /// 存入缓存后经过指定时间过期
        /// </summary>
        /// <param name="seconds">指定时间长度</param>
        public void ChangeAbsoluteExpiration(int seconds)
        {
            _cacheItemPolicy = new AbsoluteCacheItemPolicy(seconds);
        }

        /// <summary>
        /// 存入缓存后经过指定时间未访问则过期，有访问则重新计时
        /// </summary>
        /// <param name="expireTimeSpan">过期时间长度</param>
        public void ChangSlidingExpiration(TimeSpan expireTimeSpan)
        {
            _cacheItemPolicy = new SlidingCacheItemPolicy(expireTimeSpan);
        }

        /// <summary>
        /// 存入缓存后经过指定时间未访问则过期，有访问则重新计时
        /// </summary>
        /// <param name="seconds">过期时间长度</param>
        public void ChangSlidingExpiration(int seconds)
        {
            _cacheItemPolicy = new SlidingCacheItemPolicy(seconds);
        }

        /// <summary>
        /// 获取缓存值
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="key">主键</param>
        /// <returns>缓存值</returns>
        public T GetValue<T>(string key)
        {
            var content = _cache[key];
            if (content == null)
            {
                return default(T);
            }

            return (T)content;
        }

        /// <summary>
        /// 设置缓存值
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="key">主键</param>
        /// <param name="value">需缓存的值</param>
        public void SetValue<T>(string key, T value)
        {
            _cache.Set(key, value, _cacheItemPolicy.GetCacheItemPolicy());
        }

        /// <summary>
        /// 设置相对缓存值
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="key">主键</param>
        /// <param name="value">值</param>
        /// <param name="seconds">过期时间</param>
        public void SetSlidingValue<T>(string key, T value, int seconds)
        {
            _cache.Set(key, value, new CacheItemPolicy() { SlidingExpiration = new TimeSpan(0, 0, seconds) });
        }

        /// <summary>
        /// 设置绝对缓存值
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="key">主键</param>
        /// <param name="value">值</param>
        /// <param name="seconds">持续时间</param>
        public void SetAbsoluteValue<T>(string key, T value, int seconds)
        {
            _cache.Set(key, value, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(seconds) });
        }

        /// <summary>
        /// 设置绝对缓存值
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="key">主键</param>
        /// <param name="value">值</param>
        /// <param name="expireTime">过期时间</param>
        public void SetAbsoluteValue<T>(string key, T value, DateTimeOffset expireTime)
        {
            _cache.Set(key, value, new CacheItemPolicy() { AbsoluteExpiration = expireTime });
        }

        /// <summary>
        /// 移除缓存值
        /// </summary>
        /// <param name="key">主键</param>
        public void Clear(string key)
        {
            var content = _cache[key];
            if (content != null)
            {
                _cache.Set(key, content, new CacheItemPolicy() { AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(-1) });
            }
        }

        /// <summary>
        /// 获取缓存的字符串
        /// </summary>
        /// <param name="key">主键</param>
        /// <returns></returns>
        public string GetString(string key)
        {
            var content = _cache[key] as string;
            if (content == null)
            {
                return string.Empty;
            }
            return content;
        }

        /// <summary>
        /// 将字符串存入缓存
        /// </summary>
        /// <param name="key">主键</param>
        /// <param name="value">值</param>
        public void SetString(string key, string value)
        {
            _cache.Set(key, value, _cacheItemPolicy.GetCacheItemPolicy());
        }

        /// <summary>
        /// 尝试获得指定值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="TOut"></param>
        /// <returns></returns>
        public bool TryGet<T>(string key, out T TOut)
        {
            var content = _cache[key];

            TOut = content == null ? default(T) : (T)content;

            return content == null;
        }
    }
}
